<template>
    <div>
        <ul class="menu-content" :style="{top: `${menuPositnTop}px`,left: `${menuPositnLeft}px`}">
            <li v-for="item in menuList" :key='item.text' class="menu target-click" :class="{'disabled': getLimit(item.key)}"
                @click="actionHandler($event,item)">
                <component :is="item.slot"  v-if='item.slot != undefined' :showFlag='showFlag' :ele='item' @inputBack='$set(item,"other",$event)'/>
                <span v-else class='target-click'>{{item.text}}</span>
            </li>
        </ul>
        <editDrawer ref="ref_edit_drawer"/>
        <lookDrawer ref="ref_look_drawer"/>
        <front-task-dialog ref="ref_front_dialog" @frontTask='frontTaskHandler'></front-task-dialog>
        <batchEdit ref="ref_batch_dialog" @submitBatch='submitBatchHandler'/>
    </div>
</template>
<script>
import copyACtion from './components/js/copy'
import limit from './components/js/limit'
import numberText from './components/numberText'
import { timeFormat } from '@/utils/util.js'
import { mapMutations, mapGetters, mapActions } from 'vuex'
import editDrawer from './components/edit'
import lookDrawer from './components/look'
import batchEdit from './components/batchEdit'
import frontTaskDialog from './components/frontTaskDialog'
import {
    publishPIPlanActivity,
    unPublishPIPlanActivity,
    deleteNode,
    restartTask
} from "@api/planComponent";
export default {
    inject: ['setMinMaxDate','mathWorkTime','loadingTable','saveData'],
    mixins:[copyACtion,limit],
    components: {
        editDrawer,
        numberText,
        lookDrawer,
        frontTaskDialog,
        batchEdit
    },
    props: {
        showFlag: {
            type: Boolean,
            default: false
        },
        menuPositnTop: {
            type: Number,
            default: 0
        },
        menuPositnLeft: {
            type: Number,
            default: 0
        },
        menuRecord: {
            type: Object,
            default: null
        }
    },
    computed: {
        ...mapGetters({
            showSource: 'getPlanTable',
            isLastChildNode: 'isLastChildNode',
            isAddNode: 'isAddNode',
            getRowEditable: 'getRowEditable',
            getAllChildNodeByParent: 'getAllChildNodeByParent',
            getAllTable: 'getAllTable',
            getDependcyDate: 'getDependcyDate'
        })
    },
    watch: {
        menuRecord: {
            handler(n) {
                const result = n['lock.locked'] != undefined && n['lock.locked'] ? '解锁' : '锁定'
                this.menuList[this.menuList.findIndex(item => item.key == '锁定')].text = result
            },
            deep: true,
        }
    },
    data() {
        return {
            dateFormat: 'YYYY-MM-DD',
            menuList: [
                {
                    text: '编辑任务',
                    key: '编辑任务',
                    func: this.edit
                },
                {
                    text: '批量编辑',
                    key: '批量编辑',
                    func: this.editPerson
                },
                {
                    text: '查看任务',
                    key: '查看任务',
                    func: this.look
                },
                {
                    text: '发布任务',
                    key: '发布任务',
                    func: this.pushTask
                },
                {
                    text: '前置任务',
                    key: '前置任务',
                    func: this.frontTask
                },
                {
                    text: '撤销发布任务',
                    key: '撤销发布任务',
                    func: this.removePushTask
                },
                {
                    text: '删除任务',
                    key: '删除任务',
                    func: this.delTask
                },
                {
                    text: '锁定',
                    key: '锁定',
                    func: this.clock
                },
                {
                    text: '插入平行任务',
                    key: '插入平行任务',
                    slot: 'numberText',
                    other: 1,
                    func: this.addTask
                },
                {
                    text: '插入子任务',
                    key: '插入子任务',
                    slot: 'numberText',
                    other: 1,
                    func: this.addChildTask
                },
                {
                    text: '升级',
                    key: '升级',
                    func: this.up
                },
                {
                    text: '降级',
                    key: '降级',
                    func: this.down
                },
                {
                    text: '复制',
                    key: '复制',
                    func: this.copy
                },
                {
                    text: '剪切',
                    key: '剪切',
                    func: this.copy
                },
                {
                    text: '粘贴',
                    key: '粘贴',
                    func: this.paste,
                    disabled: this.pasteLimit
                },
                {
                    text: '重启任务',
                    key: '重启任务',
                    func: this.restartTask
                }
            ]
        }
    },
    methods: {
        ...mapActions(['addNodeOfPlanTable']),
        ...mapMutations(['setRowOfPlanTable', 'copyTableForCompare',
         'setRowOfAllPlanTable', 'delAllTable']),
        //前置任务触发
        frontTaskHandler(back) {
            let currentRow = JSON.parse(JSON.stringify(this.menuRecord))
            let targetRow = this.getAllTable().find(item => item.id == back.name)
            let delay = (back.delay && back.delay != undefined && back.delay != '') ? parseInt(back.delay) : 0
            //设置前置任务数据
            currentRow.predecessor = {
                Type: back.type,
                dependencyId: currentRow.predecessor.dependencyId != undefined ? 
                                currentRow.predecessor.dependencyId : 'PIProjectManager.model.Task-1',
                lag: delay,
                predecessor: back.name,
                predecessorOid: targetRow.oid,
                successor: currentRow.id
            }
            this.setRowOfPlanTable(currentRow)
            const dateBack = this.getDependcyDate(targetRow,currentRow['targetDuration.millis'],delay,back.type)
            
            currentRow.targetStartDate = timeFormat(dateBack.start,this.dateFormat)
            currentRow.targetEndDate = timeFormat(dateBack.end,this.dateFormat)
            this.setRowOfPlanTable(currentRow)
            this.setMinMaxDate(currentRow,this.getAllTable(),false)
        },
        //批量设置
        submitBatchHandler(list,source) {
            source.forEach(sourceItem => {
                let target = this.showSource.find(item => item.id == sourceItem.id)
                if (target) {
                    list.forEach(col => {
                        if (col.value) {
                            target[col.dataIndex] = col.value
                        }
                    })
                    this.setRowOfPlanTable(target)
                }
            })
        },
        actionHandler(ev,item) {
            if(ev.target.className.toString().indexOf('target-click') == -1)
                return;
            ev.stopPropagation();
            if(!this.getLimit(item.key) && item.func != undefined) {
                item.func(item.key,item.other)
                this.$emit('closeMenu')
            }
        },
        edit() {
            this.$refs.ref_edit_drawer.show(this.menuRecord,'编辑任务')
        },
        editPerson() {
            const self = this
            let selList = self.$store.state.planTable.hasSelectData.length == 0 ? 
                [self.menuRecord]: self.$store.state.planTable.hasSelectData;
            this.$refs.ref_batch_dialog.show(selList)
        },
        look() {
            this.$refs.ref_look_drawer.show(this.menuRecord)
        },
        frontTask() {
          this.$refs.ref_front_dialog.show(this.menuRecord)
        },
        //撤销发布任务
        removePushTask() {
            let parmasArr = []
            let selectData = this.$store.state.planTable.hasSelectData
            if (selectData.length > 0) {
                selectData.forEach(item => {
                    parmasArr.push(item.oid)
                })
            } else {
                parmasArr.push(this.menuRecord.oid)
            }
            let data = {
                oids: parmasArr
            }
            unPublishPIPlanActivity(data).then(res => {
                if (res && res.status === 200 && res.data.success) {
                    let arr = res.data.data
                    let updateListFlag = true
                    arr.forEach(item => {
                        if (item.success == 'true') {
                            this.$message.success(item.name + item.msg)
                        } else {
                            this.$message.error(item.name + item.msg)
                            updateListFlag = false
                        }
                    })
                    if (updateListFlag) {
                        if (selectData.length > 0) {
                            selectData.forEach(ele => {
                                ele.plannableStatus = 'SCHEDULED'
                                this.setRowOfPlanTable(ele)
                                this.setRowOfAllPlanTable(ele)
                                this.setAllParentStatus(ele.parentIds)
                            })
                        } else {
                            this.menuRecord.plannableStatus = 'SCHEDULED'
                            this.setRowOfPlanTable(this.menuRecord)
                            this.setRowOfAllPlanTable(this.menuRecord)
                            this.setAllParentStatus(this.menuRecord.parentIds)
                        }
                        this.copyTableForCompare()
                    }
                }else {
                    this.$message.error(res.data.message)
                }
            })
        },
        pushTask() {
            let selectData = this.$store.state.planTable.hasSelectData
            let arr = []
            if (selectData.length > 0) {
                selectData.forEach(item => {
                    arr.push(item.oid)
                })
            } else {
                arr.push(this.menuRecord.oid)
            }
            let data = {
                oids: arr
            }
            publishPIPlanActivity(data).then(res => {
                if (res && res.status === 200) {
                    if (res.data.success || res.data.success == 'success') {
                        let back = res.data.data
                        let updateListFlag = true
                        back.forEach(item => {
                            if (item.success == 'true') {
                                this.$message.success(item.name + item.msg)
                            } else {
                                this.$message.error(item.name + item.msg)
                                updateListFlag = false;
                            }
                        })
                        //如果发布成功修改该节点和所有父节点的任务状态
                        if (updateListFlag) {
                            if (selectData.length > 0) {
                                selectData.forEach(ele => {
                                    ele.plannableStatus = 'NOTOPEN'
                                    this.setRowOfPlanTable(ele)
                                    this.setRowOfAllPlanTable(ele)
                                    this.setAllParentStatus(ele.parentIds)
                                })
                            } else {
                                this.menuRecord.plannableStatus = 'NOTOPEN'
                                this.setRowOfPlanTable(this.menuRecord)
                                this.setRowOfAllPlanTable(this.menuRecord)
                                this.setAllParentStatus(this.menuRecord.parentIds)
                            }
                            this.copyTableForCompare()
                        }
                    }else {
                        this.$message.error(res.data.message)
                    }
                }
            })
        },
        //循环设置所有父节点的状态
        setAllParentStatus(parentIds,isTop){
            if (isTop) {
                //设置顶级节点
                this.setParentStatus(this.showSource[0].id,true)
            }else {
                //设置常规节点
                for(let i = parentIds.length - 1,len = 0; i >= len; i--) {
                    this.setParentStatus(parentIds[i])
                }
            }
        },
        //设置父节点的任务状态
        setParentStatus(parentId,isTop = false) {
            //父节点
            let parentNode = this.showSource.find(item => item.id == parentId)
            let tempStatus = parentNode.plannableStatus, childeNodes = []
            //父节点的下一层节点,
            if (isTop) {
                //如果isTop等于true，得到所有一级节点
                childeNodes = this.getAllTable().filter(item => item.parentIds.length == 1)
            }else {
                //得到下级节点
                childeNodes = this.showSource.filter(item => item.parentIds[item.parentIds.length - 1] == parentId)
            }
            if (childeNodes.some(data => data.plannableStatus != 'SCHEDULED')) {
            //只要有一个子节点不是未发布，则父节点是进行中(进行中有2中状态)
                tempStatus = ['INPROCESS','NOTOPEN']
            }else if(childeNodes.every(data => data.plannableStatus == 'COMPLETED')){
            //所有任务都是已完成，父节点也是已完成
                tempStatus = ['COMPLETED']
            }else if (childeNodes.every(data => data.plannableStatus == 'SCHEDULED')) {
            //所有任务都是未发布，父节点也是未发布
                tempStatus = ['SCHEDULED']
            }
            if (!tempStatus.includes(parentNode.plannableStatus)) {
                parentNode.plannableStatus = tempStatus[0]
                this.setRowOfPlanTable(parentNode)
                this.setRowOfAllPlanTable(parentNode)
                this.copyTableForCompare()
            }
        },
        addTask(flag,other) {
            for(let i = 0 ; i < other; i++){
                this.initAddData()
            }
        },
        addChildTask(flag,other) {
            for(let i = 0 ; i < other; i++){
                this.initAddData(true)
            }
        },
        //初始化新增数据
        initAddData(isChild = false) {
            const addIndex = this.showSource.filter(item => this.isAddNode(item.id)).length
            //点击行index
            const clickIndex = this.showSource.findIndex(item => item.id == this.menuRecord.id)
            //设置添加数据的默认数据
            let data = JSON.parse(JSON.stringify(this.menuRecord));
            const childLength = this.getChild(this.menuRecord).length
            
            for(let [key] of Object.entries(data)) {
                data[key] = ''
            }
            data.parentIds = JSON.parse(JSON.stringify(this.menuRecord.parentIds))
            data.id = `PIProjectManager.model.Task-${addIndex}`;
            data.oid = `PIProjectManager.model.Task-${addIndex}`;
            data.taskId = `PIProjectManager.model.Task-${addIndex}`;
            data.rowId = `PIProjectManager.model.Task-${addIndex}`;
            data.internalIndex = childLength
            data.name = ''
            data.editorReference = this.$store.state.planTable.allConfig.currentUser
            data.actionPerssion = true
            data.show = true;
            data.activityType = 'Task'
            data.isFolder = false
            data.deliverable = []
            data['lock.locked'] = false
            
            data.notDeleteable = false
            data.durationType = 'FixedDrtn'
            data.healthStatusType = 'UNAVAILABLE'
            data.plannableStatus = 'SCHEDULED'
            data.targetStartDate = timeFormat(new Date(),this.dateFormat)
            data.targetEndDate = timeFormat(new Date(),this.dateFormat)
            data["targetDuration.millis"] = 1
            data.durationUnit = 'DAYS'
            if(isChild) {
                data.parentIds.push(this.menuRecord.id.toString())
                this.showSource[clickIndex].activityType = 'WBS'
            }
            data.addNode = true
            //将数据插入到表格
            const index = clickIndex + childLength
            this.mathWorkTime(data,data.targetStartDate,data.targetEndDate);
            this.addNodeOfPlanTable({
                target: data,
                targetIndex: index + 1
            })
            this.setMinMaxDate(data,this.$store.state.planTable.planTable,false);
        },
        //给当前节点的同级节点(当前节点后面)添加parents(当前节点的id),成为子节点。且节点位置前移
        up() {
            const self = this;
            if (self.menuRecord.parentIds.length == 1) {
                self.$message.error('当前节点不能进行升级!')
                return
            }
            //当前点击节点的index
            const clickNodeInex = self.showSource.findIndex(item => item.id == self.menuRecord.id)
            //当前节点的父节点
            let parentNode = self.showSource.find(item => 
                item.id == self.menuRecord.parentIds[self.menuRecord.parentIds.length - 1])
            //找到index大于点击节点的所有同级节点和其子节点，并删除(parentIds)当前节点的父节点的id。
            //给所有同级节点和其子节点添加parentids，让他们成为当前节点的子节点
            self.showSource.forEach((ele,index) => {
                if (ele.parentIds.includes(parentNode.id) && index >= clickNodeInex) {
                    let targetIndex = ele.parentIds.findIndex(item => item == parentNode.id)
                    if (index == clickNodeInex) {
                        if (self.showSource[index + 1] != undefined && 
                            JSON.stringify(self.showSource[index + 1].parentIds) == JSON.stringify(ele.parentIds)) {
                        //如果节点升级后有子节点
                            ele.activityType = 'WBS'
                            ele.resource != undefined && (ele.resource = '')
                            ele.reviewerReference = ''
                        }else {
                            ele.activityType = 'Task'
                        }
                        ele.isFolder = false
                        ele.parentIds.splice(targetIndex,1)
                    }else {
                        //如果本来就是点击节点的子节点则不用将点解节点添加进父节点
                        if (ele.parentIds.includes(this.menuRecord.id))
                            ele.parentIds.splice(targetIndex,1)
                        else 
                            ele.parentIds.splice(targetIndex,1,this.menuRecord.id)
                    }
                    ele.show = true;
                    self.setRowOfPlanTable(ele)
                }
            })
            //刷新点击节点父节点的状态
            if (self.isLastChildNode(parentNode,false)) {
                parentNode.activityType = 'Task'
            }else {
                parentNode.activityType = 'WBS'
                parentNode.resource != undefined && (parentNode.resource = '')
                parentNode.reviewerReference = ''
            }
            self.setRowOfPlanTable(parentNode)
        },
        //点击节点和所有点击节点的子节点，成为前一个同级节点的子节点
        down() {
            //当前点击节点的index
            const currentIndex = this.showSource.findIndex(item => item.id == this.menuRecord.id);
            //得到所有同级节点
            let preNodes = this.showSource.filter((item,index) => 
                index < currentIndex && item.parentIds.join(',') == this.menuRecord.parentIds.join(','))
            
            if (preNodes.length == 0) {
                this.$message.error('当前任务不能进行降级!')
                return
            }
            //前一个同级节点
            let preNode = preNodes[preNodes.length - 1]
            //给点击节点和所有子节点添加父节点 preNode.id
            //如果点击节点没有子节点直接添加父节点id 否则 在指定位置添加
            this.showSource.forEach(ele => {
                if (ele.parentIds.includes(this.menuRecord.id) || ele.id == this.menuRecord.id) {
                    const findIndex = ele.parentIds.findIndex(sub => sub == this.menuRecord.id);
                    if (findIndex == -1) {
                        ele.parentIds.push(preNode.id)
                    } else {
                        ele.parentIds.splice(findIndex,0,preNode.id)
                    }
                    // const targetIndex = findIndex == -1 ? ele.parentIds.push(preNode.id) : ele.parentIds.splice(findIndex,0,preNode.id)
                    this.setRowOfPlanTable(ele)
                }
            })
            //刷新点击节点父节点的状态
            preNode.activityType = 'WBS'
            preNode.resource != undefined && (preNode.resource = '')
            preNode.reviewerReference = ''
            this.setRowOfPlanTable(preNode)
        },
        //重启问题
        restartTask() {
            let arr = []
            arr.push(this.menuRecord.oid)
            let data = {
                oids: arr
            }
            restartTask(data).then(res => {
                if (res && res.status === 200) {
                    if (res.data.status == 'error') {
                        this.$message.error(res.data.info)
                    }else {
                        this.$message.success('已重启任务')
                        this.menuRecord.plannableStatus = 'NOTOPEN'
                        this.setRowOfPlanTable(this.menuRecord)
                        this.setRowOfAllPlanTable(this.menuRecord)
                        this.setAllParentStatus(this.menuRecord.parentIds)
                        this.copyTableForCompare()
                    }
                }
            })
        },
        delTask() {
            const self = this;
            const param = self.saveData(true)
            if (param.updateData.length == 0 && param.addData.length == 0 && param.lineNumberData.length == 0 ) {
                let childNodes = self.getChild(self.menuRecord)
                if (childNodes.some(ele => ele.notDeleteable) || self.menuRecord.notDeleteable){
                    this.$message.error(`该任务${childNodes.length > 0 ? '或其下属任务' : ''}已汇报工时,不能删除!`)
                    return;
                }
                this.$confirm({
                    title: '删除任务',
                    content: `确定要删除该任务${ self.menuRecord.activityType == 'WBS' ? '和其下属任务' : ''}吗?`,
                    cancelText: '取消',
                    okText: '确认',
                    onOk() {
                        let canAction = true
                        //如果勾选了检查所有勾选的，如果没勾选只检查单击的
                        if (self.$store.state.planTable.hasSelectData.length > 0) {
                            self.$store.state.planTable.hasSelectData.forEach(items => {
                                if (self.showSource.some(item => (item.parentIds.includes(self.menuRecord.id) || item.id == self.menuRecord.id) &&
                                    item.plannableStatus != 'SCHEDULED')){
                                    self.$message.error('只允许删除未发布的任务!')
                                    canAction = false
                                }
                            })
                        }else {
                            if (self.showSource.some(item => (item.parentIds.includes(self.menuRecord.id) || item.id == self.menuRecord.id) &&
                                item.plannableStatus != 'SCHEDULED')) {
                                self.$message.error('只允许删除未发布的任务!')
                                canAction = false
                            }
                        }
                        if(canAction)
                            self.setDelRow();
                    },
                });
            }else {
                this.$message.error(`请在保存当前操作后,进行删除!`)
            }
        },
        //删除任务allTable仅用作得到lineNumber
        setDelRow() {
            const self = this;
            self.loadingTable(true);
            const delParams = this.delTaskAction()
            deleteNode({
                oid: self.showSource[0].oid,
                activities: JSON.stringify(delParams)
            }).then(res => {
                self.loadingTable(false);
                if (res.data.success == 'true'){
                    self.$message.success('删除成功!')
                }
                else {
                    self.$message.error(res.data.message)
                }
            })
        },
        //删除前台数据行，并返回删除的数据
        delTaskAction(getParamFlag) {
            const self = this;
            let deleteLineNumbers = []
            let delList = self.$store.state.planTable.hasSelectData.length == 0 ? 
                [self.menuRecord]: self.$store.state.planTable.hasSelectData;
            //循环需要删除的数据，得到oid作为参数，并在展示数据中删除这些数据
            delList.forEach(ele => {
                //删除节点的数量
                const delNum = (ele.activityType == 'WBS' ? self.getChild(ele).length : 0) + 1;
                //点击节点的位置(删除的位置肯定在展示数据中planTable，所以不用考虑allTable)
                const clickIndex = self.showSource.findIndex(item => item.id == ele.id)
                //直接删除新增节点,不是则加入deleteLineNumbers
                if (!self.isAddNode(ele.id)) {
                    deleteLineNumbers.push({
                        taskOid: ele.oid
                    })
                }
                self.showSource.splice(clickIndex,delNum)
                self.delAllTable({
                    index: clickIndex,
                    num: delNum
                })
                self.setDelParentNode(ele)
            })
            let allTable = this.getAllTable();
            //得到删除节点后面的节点并设置lineNumber
            let lineNum = []
            allTable.forEach((item,index) => {
                if (item.lineNumber != index) {
                    let currentRow = JSON.parse(JSON.stringify(item))
                    currentRow.lineNumber = index
                    //根据兄弟节点得到interIndex
                    const brotherNodes = allTable.filter(temp => JSON.stringify(temp.parentIds) == JSON.stringify(item.parentIds))
                    const internalIndex = brotherNodes.findIndex(temp => temp.id == item.id)
                    //如果internalIndex改变则赋值
                    let tempParams = {
                        taskOid: item.oid,
                        lineNumber: index
                    }
                    if (item.internalIndex != internalIndex) {
                        tempParams.internalIndex = internalIndex
                        currentRow.internalIndex = internalIndex
                    }
                    lineNum.push(tempParams)
                    //删除后修改lineNumber
                    self.setRowOfPlanTable(currentRow)
                    self.setRowOfAllPlanTable(currentRow)
                }
            })
            self.copyTableForCompare()
            return {
                deleteLineNumbers,
                lineNumberData: lineNum
            }
        },
        //修改原来的父节点状态
        setDelParentNode(ele) {
            let parentNode = this.showSource.find(item => item.id == ele.parentIds[ele.parentIds.length - 1])
            if (this.isLastChildNode(parentNode,false)) {
                parentNode.activityType = 'Task'
            }else {
                parentNode.activityType = 'WBS'
                parentNode.resource != undefined && (parentNode.resource = '')
                parentNode.reviewerReference = ''
            }
            this.setRowOfPlanTable(parentNode)
            this.setRowOfAllPlanTable(parentNode)
        },
        clock() {
            this.menuRecord['lock.locked'] = this.menuRecord['lock.locked'] ? false : true
            if (this.menuRecord['lock.locked']) {
                this.menuRecord['lock.lockDate'] = `${timeFormat(new Date(),this.dateFormat)}T00:00:00.0 Z`
                this.menuRecord['lock.locker'] = this.$store.state.planTable.allConfig.currentUser
            }else {
                this.menuRecord['lock.lockDate'] = ""
                this.menuRecord['lock.locker'] = ""
            }
            this.setRowOfPlanTable(this.menuRecord)
        }
    }
}
</script>
<style scoped lang='less'>
.menu-content {
    position: absolute;
    box-shadow: rgba(204, 204, 204, 0.35) 5px 5px 5px;
    border-width: initial;
    border-style: none;
    border-color: initial;
    border-image: initial;
    border-radius: 4px;
    background: #fff;
    min-width: 132px;
    z-index: 9;
    .menu {
        width: 230px;
        font-size: 14px;
        line-height: 30px;
        padding: 0 10px;
        cursor: pointer;
        &:not(.disabled):hover {
            // color: rgb(56,107,215);
            background: rgb(246,249,254);
        }
    }
    .disabled {
        color: #ddd;
        cursor: no-drop;
    }
}
</style>